package com.hhkj.admin.order.service.biz.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hhkj.admin.common.cont.NumTypeEnum;
import com.hhkj.admin.common.event.EventPublisher;
import com.ruoyi.common.utils.num.NumUtils;
import com.hhkj.admin.order.common.cont.OrderRefundConst;
import com.hhkj.admin.order.common.exception.InvalidOrderItemException;
import com.hhkj.admin.order.common.component.validator.OrderItemValidator;
import com.hhkj.admin.order.common.component.validator.OrderValidator;
import com.hhkj.admin.order.domain.Order;
import com.hhkj.admin.order.domain.OrderItem;
import com.hhkj.admin.order.domain.OrderRefund;
import com.hhkj.admin.order.domain.OrderRefundItemAsso;
import com.hhkj.admin.order.event.RefundPayoutSuccessEvent;
import com.hhkj.admin.order.model.dopo.OrderRefundDo;
import com.hhkj.admin.order.model.dopo.OrderRefundPo;
import com.hhkj.admin.order.model.req.OrderRefundReq;
import com.hhkj.admin.order.model.res.OrderRefundRes;
import com.hhkj.admin.order.service.base.OrderItemService;
import com.hhkj.admin.order.service.base.OrderRefundItemAssoService;
import com.hhkj.admin.order.service.base.OrderRefundService;
import com.hhkj.admin.order.service.base.OrderService;
import com.hhkj.admin.order.service.biz.OrderRefundBizService;
import com.hhkj.admin.order.service.extend.OrderExtendService;
import com.hhkj.admin.order.service.extend.OrderRefundExtendService;
import com.hhkj.admin.student.common.cont.StudentConst;
import com.hhkj.admin.student.service.base.StudentCourseService;
import com.hhkj.admin.student.service.base.StudentLoginLogService;
import com.ruoyi.common.base.biz.service.biz.BaseBizServiceImpl;
import com.ruoyi.common.base.model.extend.ValidError;
import com.ruoyi.common.exception.GlobalErrorListException;
import com.ruoyi.common.exception.GlobalException;
import com.ruoyi.common.utils.ListUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderRefundBizServiceImpl extends BaseBizServiceImpl<OrderRefund, OrderRefundReq, OrderRefundRes, OrderRefundDo, OrderRefundPo, OrderRefundService, OrderRefundExtendService>
        implements OrderRefundBizService {

    @Autowired
    private OrderItemService orderItemService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderExtendService orderExtendService;

    @Autowired
    private OrderRefundItemAssoService orderRefundItemAssoService;

    @Autowired
    private StudentLoginLogService studentLoginLogService;

    @Autowired
    private StudentCourseService studentCourseService;

    @Autowired
    private EventPublisher eventPublisher;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderRefund applyRefund(OrderRefundReq orderRefundReq, boolean isAdminApply) {
        //获取子订单信息
        List<OrderItem> orderItemList = orderItemService.listByIdList(orderRefundReq.getOrderItemIdList());
        if (ObjectUtil.isEmpty(orderItemList)) {
            throw new GlobalException("子订单为空，请检查");
        }
        Long orderId = CollectionUtil.getFirst(orderItemList).getOrderId();
        Order order = orderExtendService.getByIdNotNull(orderId);
        if (isAdminApply == false) {
            //判断订单是否是可以退款的状态
            isRefundableOrder(order);

            //判断子订单是否可以退款
            List<ValidError<OrderItem>> errorList = isRefundableOrderItemList(orderItemList, order);
            if (CollectionUtil.isEmpty(errorList) == false) {
                throw new GlobalErrorListException(errorList);
            }
        }

        //保存退款信息（包括关联信息）
        return save(orderItemList, order, orderRefundReq);
    }

    private OrderRefund save(List<OrderItem> orderItemList, Order order, OrderRefundReq orderRefundReq) {
        //批量设置学员账号不可登录(禁用状态)
        List<Long> studentCourseIdList = ListUtils.listField(orderItemList, OrderItem::getStudentCourseId);
        studentCourseService.updateBatchStatusByIdList(studentCourseIdList, StudentConst.AuditCode.STATUS_DISABLED.getCode());

        //获取今日退款数量，用于生成退款单号
        Long count = getService().countByToday();
        //获取退款总金额
        BigDecimal price = orderItemList.stream().map(OrderItem::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);

        //创建退款记录
        OrderRefund orderRefund = OrderRefund.builder()
                .num(NumUtils.generateNum(NumTypeEnum.REFUND.getPrefix(), ++count))
                .statusCode(OrderRefundConst.StatusEnum.REFUNDING.getCode())
                .startTime(new Date())
                .price(price)
                .studentAmount(orderItemList.size())
                .accountName(orderRefundReq.getAccountName())
                .account(orderRefundReq.getAccount())
                .description(orderRefundReq.getDescription())
                .orderId(order.getId()).build();
        this.getService().save(orderRefund);

        List<OrderRefundItemAsso> orderRefundItemAssoList = orderItemList.stream().map(orderItem -> {
            //设置子订单退款状态
            orderItem.setRefundStatusCode(OrderRefundConst.StatusEnum.REFUNDING.getCode());
            //设置退款单和退款学员的关联
            OrderRefundItemAsso orderRefundItemAsso = new OrderRefundItemAsso();
            orderRefundItemAsso.setRefundId(orderRefund.getId());
            orderRefundItemAsso.setOrderItemId(orderItem.getId());
            return orderRefundItemAsso;
        }).collect(Collectors.toList());
        //保存子订单与退款记录的关联关系
        orderRefundItemAssoService.saveBatch(orderRefundItemAssoList);

        //更新子订单
        orderItemService.updateBatchById(orderItemList);

        //更新订单
        order.setRefundStatusCode(OrderRefundConst.StatusEnum.REFUNDING.getCode());
        orderService.updateById(order);
        return orderRefund;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderRefund agreeRefund(OrderRefundReq orderRefundReq) {
        Long orderId = orderRefundReq.getOrderId();

//        //是否是可以退款的订单
//        Order order = isRefundableOrder(orderId);
//
//        //查询子订单列表
//        OrderItemDo orderItemDo = new OrderItemDo();
//        orderItemDo.setOrderId(orderId);
//        List<OrderItemPo> orderItemPoList = orderItemService.listPoByDo(orderItemDo);
//
//        //判断子订单是否可以退款
//        List<ValidError<OrderItem>> errorList = isRefundableOrderItemList(orderItemPoList, order);
//        if (CollectionUtil.isEmpty(errorList) == false) {
//            throw new GlobalErrorListException(errorList);
//        }

        //查看是否存在正在处理中的退款
        OrderRefundDo orderRefundDo = new OrderRefundDo();
        orderRefundDo.setOrderId(orderId);
        orderRefundDo.setStatusCode(OrderRefundConst.StatusEnum.REFUNDING.getCode());
        OrderRefundPo orderRefundPo = getService().getPoByDo(orderRefundDo);
        if(ObjectUtil.isEmpty(orderRefundPo)) {
            throw new GlobalException("该订单不存在正在处理中的退款");
        }

        //修改订单退款状态
        orderRefundPo.setPayoutStatusCode(OrderRefundConst.PayoutStatusCode.PENDING.getCode());
        orderRefundPo.setAuditDescription(orderRefundReq.getAuditDescription());
        this.getService().updateById(orderRefundPo);
        return orderRefundPo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean payout(OrderRefundReq orderRefundReq, Long createBy) {
        //查看是否存在正在等待打款的退款
        OrderRefundPo orderRefundPo = getService().getAgreedRefundPo(orderRefundReq.getOrderId());
        if(ObjectUtil.isEmpty(orderRefundPo)) {
            throw new GlobalException("该订单不存在正在等待打款的退款");
        }

        //实际退款金额超出了支付的金额
        if (orderRefundReq.getFinalPrice().compareTo(orderRefundPo.getPrice()) > 0) {
            throw new GlobalException("实际退款金额不正确，请检查");
        }
        Order order = orderExtendService.getByIdNotNull(orderRefundReq.getOrderId());
        if (orderRefundReq.getFinalPrice().compareTo(order.getFinalPrice()) > 0) {
            throw new GlobalException("实际退款金额不正确，请检查");
        }

        //修改退款状态
        orderRefundPo.setPayoutStatusCode(OrderRefundConst.PayoutStatusCode.DONE.getCode());
        orderRefundPo.setStatusCode(OrderRefundConst.StatusEnum.SUCCESS.getCode());
        orderRefundPo.setPayoutDate(orderRefundReq.getPayoutDate());
        orderRefundPo.setEndTime(new Date());
        orderRefundPo.setPayoutReceiptUrl(orderRefundReq.getPayoutReceiptUrl());
        orderRefundPo.setFinalPrice(orderRefundReq.getFinalPrice());
        orderRefundPo.setUpdateBy(createBy);
        this.getService().updateById(orderRefundPo);

        //修改订单退款状态和实际订单价格 -
        order.setRefundStatusCode(OrderRefundConst.StatusEnum.SUCCESS.getCode());
        order.setFinalPrice(order.getFinalPrice().subtract(orderRefundReq.getFinalPrice()));
        order.setUpdateBy(createBy);
        orderService.updateById(order);

        //修改子订单item -
        LambdaQueryWrapper<OrderRefundItemAsso> queryWrapper = new LambdaQueryWrapper<OrderRefundItemAsso>()
                .eq(OrderRefundItemAsso::getRefundId, orderRefundPo.getId());
        List<OrderRefundItemAsso> list = orderRefundItemAssoService.list(queryWrapper);
        List<Long> orderItemIdList = list.stream().map(OrderRefundItemAsso::getOrderItemId).collect(Collectors.toList());
        orderItemService.updateRefundStatusBatch(orderItemIdList, OrderRefundConst.StatusEnum.SUCCESS);

        //设置学员课程为过期
        List<OrderItem> orderItemList = orderItemService.listByIdList(orderItemIdList);
        List<Long> studentCourseIdList = ListUtils.listField(orderItemList, OrderItem::getStudentCourseId);
        studentCourseService.updateBatchStatusByIdList(studentCourseIdList, StudentConst.AuditCode.STATUS_OUT_TIME.getCode());

        //修改返佣
        eventPublisher.sendEvent(new RefundPayoutSuccessEvent(order));
        return true;
    }

    /**
     * 校验是否属于可以退款的订单
     * @param order
     * @return
     */
    public boolean isRefundableOrder(Order order) {
//        //判断订单是否属于当前商家
//        OrderValidator.isSelfOrder(order);

        //判断订单是否已经支付
        OrderValidator.isPaidOrder(order);
        //判断订单退款状态是否属于可以退款
        OrderValidator.isNotRefundingOrder(order);
        //判断订单是否超过24小时
        OrderValidator.isOrderOutOf24Hour(order);
        return true;
    }

    /**
     * 校验是否属于可以退款的子订单
     * @param orderItemList 子订单列表
     * @param order 所属订单
     * @return
     */
    public List<ValidError<OrderItem>> isRefundableOrderItemList(List<? extends OrderItem> orderItemList, Order order) {
        List<ValidError<OrderItem>> validErrorList = new ArrayList<>();
        List<String> idCardList = orderItemList.stream().map(OrderItem::getIdCard).collect(Collectors.toList());
        Map<String, Set<Long>> idCardCourseIdSetMap = studentLoginLogService.courseIdSetGroupByIdCard(idCardList, order.getPayTime(), null);
        int i = 0;
        OrderItem orderItem = null;
        for (; i < orderItemList.size(); i++) {
            try {
                orderItem = orderItemList.get(i);
                //判断子订单是否都来自于同一个订单
                OrderItemValidator.isBelongThisOrder(orderItem, order.getId());
                //判断子订单是否处于可申请退款的状态
                OrderItemValidator.isRefundableStatus(orderItem);
                //判断学员是否已经登录过
                Set<Long> courseIdSet = idCardCourseIdSetMap.get(orderItem.getIdCard());
                if (ObjectUtil.isNotEmpty(courseIdSet) && courseIdSet.contains(orderItem.getCourseId())) {
                    throw new InvalidOrderItemException(orderItem.getName() + "已经登录，不允许退款");
                }
            } catch (InvalidOrderItemException e) {
                validErrorList.add(new ValidError<>(i + 1, orderItem, e.getMessage()));
            }
        }
        return validErrorList;
    }
}
